package com.moss.cloud.common.file.realize;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSONObject;
import com.moss.cloud.common.file.exception.StorageErrorType;
import com.moss.cloud.common.file.exception.StorageException;
import com.moss.cloud.common.file.model.GoFastDfsRes;
import com.moss.cloud.common.file.model.GoFastDfsUploadResult;
import com.moss.cloud.common.file.model.StorageModel;
import com.moss.cloud.common.file.model.UploadRes;
import com.moss.cloud.common.file.operation.FileStorageOperation;
import com.moss.cloud.common.file.utils.FileDataPreUtil;
import com.moss.cloud.common.file.utils.UUIDUtil;
import com.moss.cloud.common.file.utils.UploadResUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author chengming
 * @since 2024/3/4
 */
@Slf4j
public class GoFastDfsStorage implements FileStorageOperation {
    @Override
    @SneakyThrows
    public UploadRes upload(StorageModel storageModel) {
        // 文件名
        String fileName = storageModel.getIsBase64() ? storageModel.getName() : storageModel.getMultipartFile().getOriginalFilename();
        FileDataPreUtil.isSizeAllowed(storageModel);
        FileDataPreUtil.isAllowed(fileName, storageModel.getStorageConfig().getSuffix());

        // Go fast dfs组名
        String groupName = storageModel.getStorageConfig().getBucket();
        String renameFileName = UUIDUtil.rename(fileName);
        String uploadPath = String.format("%s/%s/upload", storageModel.getStorageConfig().getBaseUrl(), groupName);

        byte[] bytes;
        if (storageModel.getInputStream() == null) {
            if (storageModel.getIsBase64()) {
                bytes = FileDataPreUtil.base64ToBytes(storageModel.getImgBase64());
            } else {
                bytes = storageModel.getMultipartFile().getBytes();
            }
        } else {
            bytes = this.toByteArray(storageModel.getInputStream());
        }

        OkHttpClient httpClient = new OkHttpClient();
        MultipartBody multipartBody = new MultipartBody
                .Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("file", fileName, RequestBody.create(bytes, MediaType.parse("multipart/form-data;charset=utf-8")))
                .addFormDataPart("output", "json")
                .build();

        Request request = new Request
                .Builder()
                .url(uploadPath)
                .post(multipartBody)
                .build();

        Response response = httpClient
                .newCall(request)
                .execute();

        String result = "";
        if (response.isSuccessful()) {
            ResponseBody body = response.body();
            if (Objects.nonNull(body)) {
                result = body.string();
            }
        } else {
            log.error("文件上传失败: {}", response);
            throw new StorageException(StorageErrorType.STORAGE_ERROR);
        }

        if (!result.contains("src")) {
            // 失败
            GoFastDfsRes goFastDfsRes = JSONObject.parseObject(result, GoFastDfsRes.class);
            log.error("文件上传失败：{}", goFastDfsRes.getMessage());
            throw new StorageException(StorageErrorType.STORAGE_ERROR);
        }

        GoFastDfsUploadResult goFastDfsUploadResult = JSONObject.parseObject(result, GoFastDfsUploadResult.class);
        String path = goFastDfsUploadResult.getDomain() + goFastDfsUploadResult.getPath();

        return UploadResUtil.createUploadRes(path, renameFileName, storageModel.getStorageConfig().getType());
    }

    @Override
    public void removeFile(StorageModel storageModel) {
        String groupName = storageModel.getStorageConfig().getBucket();
        String path = storageModel.getFileId();
        String deletePath = storageModel.getStorageConfig().getBaseUrl() + "/" + groupName + "/" + "delete";

        Map<String, Object> params = new HashMap<>();
        params.put("path", path);
        HttpUtil.post(deletePath, params);
    }

    public byte[] toByteArray(InputStream input) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        byte[] buffer = new byte[1024];
        int length;
        while ((length = input.read(buffer)) != -1) {
            outputStream.write(buffer, 0, length);
        }

        //关闭输出流并获取字节数组
        outputStream.close();
        return outputStream.toByteArray();
    }
}
